/**
 * Copyright:Copyright(c)2014-2017
 * Company:厦门市易致达物联网科技有限公司
 *
 * @version 1.0
 */
package shop.controller.front.orderpay;

import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import shop.core.FrontBaseController;
import shop.core.RequestHolder;
import shop.core.Services;
import shop.core.common.bean.JSONResult;
import shop.core.plugins.wxmsg.WxMsgUtil;
import shop.core.plugins.wxpay.WXPay;
import shop.core.plugins.wxpay.WXPayConfigImpl;
import shop.core.plugins.wxpay.WXPayConstants;
import shop.core.plugins.wxpay.WXPayUtil;
import shop.core.util.AddressUtils;
import shop.services.front.brokerage.BrokerageService;
import shop.services.front.entrepot.EntrepotService;
import shop.services.front.entrepot.bean.Entrepot;
import shop.services.front.order.OrderService;
import shop.services.front.order.bean.Order;
import shop.services.front.orderdetail.OrderdetailService;
import shop.services.front.orderdetail.bean.Orderdetail;
import shop.services.front.orderpay.OrderpayService;
import shop.services.front.orderpay.bean.Orderpay;
import shop.services.front.product.ProductService;
import shop.services.front.product.bean.Product;
import shop.services.front.rank.RankService;
import shop.services.front.rank.bean.Rank;
import shop.services.front.record.RecordService;
import shop.services.front.record.bean.Record;
import shop.services.front.spec.SpecService;
import shop.services.front.spec.bean.Spec;
import shop.services.manage.system.bean.User;
import shop.services.manage.system.impl.UserService;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.BufferedReader;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.*;

/**
 * @类名称：OrderpayController
 * @创建人：Wzl
 * @创建时间：2017-09-20 下午15:50:16
 * @版本号：1.0
 * @描述：订单支付
 */
@Controller
@RequestMapping("/front/orderpay/")
public class OrderpayController extends FrontBaseController<Orderpay> {
    @Resource
    private OrderpayService orderpayService;
    @Resource
    private OrderService orderService;
    @Resource
    private ProductService productService;
    @Resource
    private SpecService specService;
    @Resource
    private EntrepotService entrepotService;
    @Resource
    private OrderdetailService orderdetailService;
    @Resource
    private RecordService recordService;
    @Resource
    private UserService userService;
    @Resource
    private RankService rankService;

    private WXPay wxpay;
    private WXPayConfigImpl config;

    @Override
    public Services<Orderpay> getService() {
        return orderpayService;
    }

    /**
     * 获取预支付信息
     *
     * @param session
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "getPrepayId", method = RequestMethod.GET)
    @ResponseBody
    public JSONResult getPrepayId(HttpSession session, Order order) throws Exception {
        JSONResult jsonResult = new JSONResult();
        order.setStatus("init");
        String out_trade_no = UUID.randomUUID().toString().replace("-", "");//商户订单号
        DecimalFormat df = new DecimalFormat("######0.00");//格式化数据
        User user = (User) session.getAttribute("userInfo");//获取登陆用户
        String orderID = "";
        if (!StringUtils.isBlank(order.getId())) {
            logger.debug("已有订单：" + order.getId());
            orderID = order.getId();
        } else {
            // 获取支付表的订单ID
            orderID = (String) getOrderID(user, order).getData();
        }
        config = WXPayConfigImpl.getInstance();
        wxpay = new WXPay(config);
        BigDecimal orderPtotal = order.getPtotal();
        Float rs = orderPtotal.floatValue() * 100;
        String total_fee = String.valueOf(rs.intValue());//商品总价
        HashMap<String, String> data = new HashMap<String, String>();
        data.put("body", "袋泡茶");//商品描述
        data.put("out_trade_no", out_trade_no);//商户订单号
        data.put("device_info", "");//设备号
        data.put("total_fee", total_fee);//标价金额
        String clientIp = AddressUtils.getIp(RequestHolder.getRequest()).split(",")[0];
        data.put("spbill_create_ip", clientIp);//终端IP
        data.put("notify_url", "http://agent.finebeiy.com/rest/front/orderpay/notify");//通知地址
        data.put("trade_type", "JSAPI");//交易类型
        data.put("product_id", UUID.randomUUID().toString().replace("-", ""));//商品ID
        data.put("openid", session.getAttribute("userOpenId").toString());//用户标识
        logger.debug("data数据信息：" + data);

        try {
            Map<String, String> r = wxpay.unifiedOrder(data);
            logger.debug("获得预支付信息为：" + r.get("return_msg") + ",获得返回状态码为：" + r.get("return_code"));
            //回传页面参数
            Map<String, String> reqData = new HashMap<String, String>();
            reqData.put("appId", config.getAppID());//公众账号ID
            reqData.put("timeStamp", String.valueOf(new Date().getTime() / 1000));//生成签名的时间戳
            reqData.put("nonceStr", r.get("nonce_str"));//随机字符串
            reqData.put("signType", "MD5");//签名类型
            reqData.put("package", "prepay_id=" + r.get("prepay_id"));//预支付交易会话标识
            String paySign = WXPayUtil.generateSignature(reqData, config.getKey(), WXPayConstants.SignType.MD5);//获取微信支付签名
            reqData.put("paySign", paySign);//签名
            logger.debug("回传页面参数填写完成：" + reqData);
            //插入订单支付表
            Orderpay orderpay = new Orderpay();
            orderpay.setOrderID(orderID);
            Orderpay anOrderpay = orderpayService.selectOne(orderpay);
            if (anOrderpay != null) {
                anOrderpay.setPrepayId(r.get("prepay_id"));//赋值,预支付ID
                anOrderpay.setOutTradeNo(out_trade_no);//赋值,商户订单号
                getService().update(anOrderpay);//更新订单支付信息
                jsonResult.setData(reqData);//回传页面参数
                return jsonResult;
            } else {
                orderpay.setPayStatus("0");//赋值,支付状态
                orderpay.setPrepayId(r.get("prepay_id"));//赋值,预支付ID
                orderpay.setPayType(data.get("trade_type"));//赋值,交易类型
                orderpay.setPayAmount(order.getPtotal());//赋值,支付金额
                orderpay.setOutTradeNo(out_trade_no);//赋值,商户订单号
                orderpay.setProductBody(data.get("body"));//赋值,商品描述
                getService().insert(orderpay);//插入订单支付表
                jsonResult.setData(reqData);//回传页面参数
                return jsonResult;
            }
        } catch (Exception e) {
            logger.debug("打印错误日志：");
            e.printStackTrace();
            jsonResult.setSuccess(false);
            return jsonResult;
        }
    }

    /**
     * 微信支付回调接口
     *
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "notify", produces = "application/xml;charset=UTF-8")
    @ResponseBody
    public String payNotifyUrl(HttpServletRequest request, HttpServletResponse response) throws Exception {
        DecimalFormat df = new DecimalFormat("######0.00");//设定double格式，保留两位小数
        BufferedReader reader = request.getReader();//读取输入字符
        String line = "";
        String xmlString = null;
        StringBuffer inputString = new StringBuffer();
        while ((line = reader.readLine()) != null) {
            inputString.append(line);
        }
        xmlString = inputString.toString();
        request.getReader().close();//关闭输入流
        Map<String, String> receiveData = WXPayUtil.xmlToMap(xmlString);
        logger.debug("收到支付回调结果:" + receiveData);
        String out_trade_no = receiveData.get("out_trade_no");
        Orderpay orderpay = new Orderpay();
        orderpay.setOutTradeNo(out_trade_no);//赋值,商户订单号
        orderpay = getService().selectOne(orderpay);//查询支付记录
        logger.debug("查询本地支付记录：" + orderpay);
        String orderID = orderpay.getOrderID();
        String rsType = receiveData.get("return_code");//返回状态码
        HashMap<String, String> data = new HashMap<String, String>();
        String reStr = "";
        if (rsType.equals("SUCCESS")) {//判断交易是否成功
            reStr = updateData(receiveData, data, orderpay, reStr, orderID);
            //订单付款成功消息通知
            Order order = new Order();
            order.setId(orderID);
            order = orderService.selectOne(order);
            Orderdetail orderdetail = new Orderdetail();
            orderdetail.setOrderID(orderID);
            List<Orderdetail> orderdetailList = orderdetailService.selectList(orderdetail);
            orderdetail.setId(orderdetailList.get(0).getId());
            orderdetail = orderdetailService.selectOne(orderdetail);
            User user = new User();
            user.setId(order.getUserID());
            user = userService.selectOne(user);
            if ("rank".equals(order.getType())) {
                Map<String, String> msgParam = new HashMap<>();
                msgParam.put("first", "亲爱的" + user.getNickname() + "，恭喜您成为" + order.getRankType());
                msgParam.put("keyword1", user.getNickname());
                msgParam.put("keyword2", order.getRankType());
                msgParam.put("remark", "点击查看订单详情");
                if ("y".equals(user.getRankPayStatus()))
                    WxMsgUtil.sendRankFinishMsg(msgParam, systemManager.getAccessToken(), user.getOpenID());
            } else {
                Map<String, String> msgParam = new HashMap<>();
                msgParam.put("first", "亲爱的" + user.getNickname() + "，您的订单已经付款成功了~，正在秒速为您安排发货，请耐心等待哦~");
                msgParam.put("keyword1", order.getPtotal().toString());
                msgParam.put("keyword2", orderdetail.getProductName());
                msgParam.put("keyword3", order.getAddressArea() + order.getAddressDetail());
                msgParam.put("keyword4", orderID);
                msgParam.put("remark", "点击查看订单详情");
                if ("y".equals(user.getOrderPayStatus()))
                    WxMsgUtil.sendPaySuccessMsg(msgParam, systemManager.getAccessToken(), user.getOpenID());
            }
            //下级用户下单通知
            if (!"0".equals(user.getPid())) {
                User supUser = new User();
                supUser.setId(user.getPid());
                supUser = userService.selectOne(supUser);
                Map<String, String> msgParam2 = new HashMap<>();
                msgParam2.put("first", "亲爱的" + supUser.getNickname() + "，您有一个分销订单请尽快处理哦~");
                msgParam2.put("keyword1", order.getCreateTime());
                msgParam2.put("keyword2", order.getAddressName());
                msgParam2.put("keyword3", order.getAddressPhone());
                msgParam2.put("keyword4", order.getAddressArea() + order.getAddressDetail());
                msgParam2.put("remark", "点击查看订单详情");
                if ("y".equals(user.getOrderSubPayStatus()))
                    WxMsgUtil.sendSubOrderMsg(msgParam2, systemManager.getAccessToken(), supUser.getOpenID());
            }
        } else {
            data.put("return_code", "FAIL");
            data.put("return_msg", "支付失败");
            reStr =  "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
                    + "<return_msg><![CDATA[支付失败]]></return_msg>" + "</xml> ";
            //订单付款失败消息通知
            Order order = new Order();
            order.setId(orderID);
            order = orderService.selectOne(order);
            Orderdetail orderdetail = new Orderdetail();
            orderdetail.setOrderID(orderID);
            List<Orderdetail> orderdetailList = orderdetailService.selectList(orderdetail);
            orderdetail.setId(orderdetailList.get(0).getId());
            orderdetail = orderdetailService.selectOne(orderdetail);
            User user = new User();
            user.setId(order.getUserID());
            user = userService.selectOne(user);
            Map<String, String> msgParam = new HashMap<>();
            msgParam.put("first", "亲爱的" + user.getNickname() + "，请尽快处理未付款的订单，超时会自动关闭哟~");
            msgParam.put("keyword1", order.getCreateTime());
            msgParam.put("keyword2", orderdetail.getPtotal().toString());
            msgParam.put("keyword3", orderdetail.getProductName());
            msgParam.put("remark", "感谢您对纤纤蓓颖商城的支持！点击【详情】支付~");
            if ("y".equals(user.getOrderUnPayStatus()))
                WxMsgUtil.sendPayFailedMsg(msgParam, systemManager.getAccessToken(), user.getOpenID());
        }
        logger.debug("返回支付状态消息给微信："+reStr);
        return reStr;
    }


    /**
     * 获取订单ID
     *
     * @param order
     * @return
     * @throws Exception
     */
    private JSONResult getOrderID(User user, Order order) throws Exception {
        String orderID = "";
        // 获取支付表的订单ID
        if (user == null)
            return JSONResult.error("您还未进行授权，无法购物");//判断用户是否授权登陆
        Order orderInfo = new Order();
        orderInfo.setUserID(user.getId());
        orderInfo.setCheckStatus("init");
        orderInfo = orderService.selectOne(orderInfo);
        if (orderInfo != null)
            return JSONResult.error("您的线下支付申请正在审核，请耐心等待！");//判断用户是否重复购买会员
        logger.debug("插入订单：");
        String[] productIDs = order.getProductIDs().split(",");
        String[] specIDs = order.getSpecIDs().split(";");
        String[] productAmount = order.getProductAmount().split(",");
        for (int i = 0; i < productIDs.length; i++) {
            Spec spec = new Spec();
            spec.setProductID(productIDs[i]);
            spec.setSpecCombination(specIDs[i]);
            spec = specService.selectOne(spec);//查询该件商品库存
            Product productInfo = new Product();
            productInfo.setId(productIDs[i]);
            productInfo = productService.selectOne(productInfo);//查询该件商品
            if (((spec.getSpecStock() - Integer.parseInt(productAmount[i])) <= 0))
                return JSONResult.error(productInfo.getName() + "商品库存不足，请重新下单!");
        }
        order.setUserID(user.getId());
        logger.debug("订单pid: " + order.getPid());
        orderID = String.valueOf(orderService.insert(order));
        logger.debug("订单ID：" + orderID);
        JSONResult jsonResult = new JSONResult();
        jsonResult.setData(orderID);
        return jsonResult;
    }

    /**
     * 支付数据维护
     *
     * @param
     * @return
     * @throws Exception
     */
    private String updateData(Map<String, String> receiveData, HashMap<String, String> data, Orderpay orderpay, String reStr, String orderID) throws Exception {
        //查询该条订单
        Order order = orderService.selectById(orderID);
        //查询登陆用户
        User loginUser = new User();
        loginUser.setId(order.getUserID());
        loginUser = userService.selectOne(loginUser);
        logger.debug("支付返回订单信息：" + order.getStatus());
        if (order.getStatus().equals("init")) {
            Orderdetail orderdetail = new Orderdetail();
            orderdetail.setOrderID(orderID);
            //查询订单详情列表
            List<Orderdetail> orderdetailList = orderdetailService.selectList(orderdetail);
            //遍历订单详情
            for (Orderdetail anOrdedetail : orderdetailList) {
                Product product = new Product();
                product.setId(anOrdedetail.getProductID());
                //查询商品信息
                product = productService.selectOne(product);
                if ("order".equals(order.getType())) {
                    updateOrderData(anOrdedetail, product, loginUser, order);
                } else if ("rank".equals(order.getType()) && "online".equals(order.getPayType())) {
                    updateRankData(anOrdedetail, product, loginUser, order);
                } else {
                }
            }
            // 更新订单状态
            logger.debug("更新订单状态");
            if ("2".equals(loginUser.getRid()) || "rank".equals(order.getType())) {
                order.setStatus("finish");
            } else {
                order.setStatus("pass");
            }
            orderService.update(order);
        }
        //更新本地订单支付表信息
        logger.debug("更新本地订单支付表信息：" + orderpay);
        orderpay.setTransactionId(receiveData.get("transaction_id"));
        orderpay.setPayStatus("1");
        getService().update(orderpay);
        data.put("return_code", "SUCCESS");
        data.put("return_msg", "OK");
        reStr = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"
                + "<return_msg><![CDATA[OK]]></return_msg>"
                + "</xml> ";
        return reStr;
    }

    /**
     * 支付数据维护(购买商品)
     *
     * @param
     * @throws Exception
     */
    private void updateOrderData(Orderdetail anOrdedetail, Product product, User loginUser, Order order) throws Exception {
        if ("0".equals(loginUser.getPid())) {
            //更新平台商品库存
            Spec spec = new Spec();
            spec.setProductID(anOrdedetail.getProductID());
            spec.setSpecCombination(anOrdedetail.getSpecInfo());
            spec = specService.selectOne(spec);
            spec.setSpecStock(spec.getSpecStock() - anOrdedetail.getNumber());
            specService.update(spec);
            //更新平台商品销售量
            product.setSellcount(product.getSellcount() + anOrdedetail.getNumber());
            productService.update(product);
        } else {
            //更新上级仓库库存
            Entrepot entrepot = new Entrepot();
            entrepot.setUserID(loginUser.getPid());
            entrepot.setProductID(anOrdedetail.getProductID());
            entrepot.setSpecInfo(anOrdedetail.getSpecInfo());
            entrepot = entrepotService.selectOne(entrepot);
            entrepot.setNumber(entrepot.getNumber() - anOrdedetail.getNumber());
            entrepotService.update(entrepot);
            //上级返利
            User supUser = new User();
            supUser.setId(loginUser.getPid());
            supUser = userService.selectOne(supUser);
            supUser.setWalletMoney(supUser.getWalletMoney().add(order.getPtotal()));
            supUser.setScore(supUser.getScore().add(order.getPtotal()));//更新上级积分
            userService.update(supUser);
            //生成交易记录（上级钱包）
            Record record = new Record();
            record.setUserID(supUser.getId());
            record.setTransType("1");
            record.setTransID(order.getId());
            record.setMoney(order.getPtotal());
            recordService.insert(record);
        }
        //创建分销仓库项
        if ("2".equals(loginUser.getRid())) {
            Entrepot entrepot = new Entrepot();
            entrepot.setUserID(order.getUserID());
            entrepot.setProductID(anOrdedetail.getProductID());
            entrepot.setSpecInfo(anOrdedetail.getSpecInfo());
            entrepot = entrepotService.selectOne(entrepot);
            if (entrepot == null) {
                Entrepot entrepotInfo = new Entrepot();
                entrepotInfo.setUserID(order.getUserID());
                entrepotInfo.setProductID(anOrdedetail.getProductID());
                entrepotInfo.setSpecInfo(anOrdedetail.getSpecInfo());
                entrepotInfo.setPrice(anOrdedetail.getPrice());
                entrepotInfo.setNumber(anOrdedetail.getNumber());
                entrepotInfo.setOrderID(anOrdedetail.getOrderID());
                entrepotService.insert(entrepotInfo);//插入分销仓库表
            } else {
                entrepot.setNumber(entrepot.getNumber() + anOrdedetail.getNumber());
                entrepotService.update(entrepot);//更新分销仓库表
            }
        }
    }

    /**
     * 支付数据维护(升级会员)
     *
     * @param
     * @throws Exception
     */
    private void updateRankData(Orderdetail anOrdedetail, Product product, User loginUser, Order order) throws Exception {
        if ("0".equals(loginUser.getPid())) {
            //更新平台商品库存
            Spec spec = new Spec();
            spec.setProductID(anOrdedetail.getProductID());
            spec.setSpecCombination(anOrdedetail.getSpecInfo());
            spec = specService.selectOne(spec);
            spec.setSpecStock(spec.getSpecStock() - anOrdedetail.getNumber());
            specService.update(spec);
            //更新平台商品销售量
            product.setSellcount(product.getSellcount() + anOrdedetail.getNumber());
            productService.update(product);
        } else {
            //更新上级仓库库存
            Entrepot entrepot = new Entrepot();
            entrepot.setUserID(loginUser.getPid());
            entrepot.setProductID(anOrdedetail.getProductID());
            entrepot.setSpecInfo(anOrdedetail.getSpecInfo());
            entrepot = entrepotService.selectOne(entrepot);
            entrepot.setNumber(entrepot.getNumber() - anOrdedetail.getNumber());
            entrepotService.update(entrepot);
            //上级返利
            User supUser = new User();
            supUser.setId(loginUser.getPid());
            supUser = userService.selectOne(supUser);
            supUser.setWalletMoney(supUser.getWalletMoney().add(order.getPtotal()));
            supUser.setScore(supUser.getScore().add(order.getPtotal()));//更新上级积分
            userService.update(supUser);
            //生成交易记录（上级钱包）
            Record record = new Record();
            record.setUserID(supUser.getId());
            record.setTransType(order.getTransType());
            record.setTransID(order.getId());
            record.setMoney(order.getPtotal());
            recordService.insert(record);
        }
        //创建分销仓库项
        Entrepot entrepot = new Entrepot();
        entrepot.setUserID(order.getUserID());
        entrepot.setProductID(anOrdedetail.getProductID());
        entrepot.setSpecInfo(anOrdedetail.getSpecInfo());
        entrepot = entrepotService.selectOne(entrepot);
        if (entrepot == null) {
            Entrepot entrepotInfo = new Entrepot();
            entrepotInfo.setUserID(order.getUserID());
            entrepotInfo.setProductID(anOrdedetail.getProductID());
            entrepotInfo.setSpecInfo(anOrdedetail.getSpecInfo());
            entrepotInfo.setPrice(anOrdedetail.getPrice());
            entrepotInfo.setNumber(anOrdedetail.getNumber());
            entrepotInfo.setOrderID(anOrdedetail.getOrderID());
            entrepotService.insert(entrepotInfo);//插入分销仓库表
        } else {
            entrepot.setNumber(entrepot.getNumber() + anOrdedetail.getNumber());
            entrepotService.update(entrepot);//更新分销仓库表
        }
        //更新用户数据
        loginUser.setRid("2");
        Rank rank = new Rank();
        rank.setType(order.getRankType());
        rank = rankService.selectOne(rank);
        loginUser.setRankID(rank.getId());
        loginUser.setPid("0");
        userService.update(loginUser);
        User subUser = new User();
        //解除绑定的下级
        subUser.setPid(loginUser.getId());
        List<User> subUserList = userService.selectList(subUser);
        if (subUserList.size() != 0 && subUserList != null) {
            for (User userInfo : subUserList) {
                userInfo.setPid("");
                userService.update(userInfo);
            }
        }
    }
}
